// -*- C++ -*-

//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2009-06-11 23:52
 */
//========================================================================

#ifndef NDK_SOCKET_H_
#define NDK_SOCKET_H_

#include "ndk/types.h"
#include "ndk/ndk_os.h"
#include "ndk/inet_addr.h"

namespace ndk
{
  /**
   * @class socket
   * 
   * @brief 
   */
  class socket
  {
  public:
    virtual ~socket() { }
    //
    inline int open(int type, int protocol_family)
    {
      ndk_handle h = ndk_os::socket(protocol_family, type, 0);
      if (h == NDK_INVALID_HANDLE) return -1;
      this->handle_ = h;
      return 0;
    }
    //
    inline int close(void)
    {
      int result = ndk_os::closesocket(this->handle_);
      this->handle_ = NDK_INVALID_HANDLE;
      return result;
    }
    //
    inline ndk_handle get_handle() const { return this->handle_; }
    inline void set_handle(ndk_handle h) { this->handle_ = h;    }
    //
    inline int get_local_addr(inet_addr &local_addr)
    {
      int l = local_addr.get_addr_size();
      sockaddr *addr = reinterpret_cast<sockaddr*> (local_addr.get_addr());
      if (::getsockname(this->handle_, addr, (socklen_t*)&l) == -1)
        return -1;
      local_addr.set_type(addr->sa_family);
      return 0;
    }
    //
    inline int get_remote_addr(inet_addr &remote_addr)
    {
      int l = remote_addr.get_addr_size();
      sockaddr *addr = reinterpret_cast<sockaddr*> (remote_addr.get_addr());
      if (::getpeername(this->handle_, addr, (socklen_t*)&l) == -1)
        return -1;
      remote_addr.set_type(addr->sa_family);
      return 0;
    }
  protected:
    socket()
    : handle_(NDK_INVALID_HANDLE)
    { }

    ndk_handle handle_;
  };
} // namespace ndk

#endif // NDK_SOCKET_H_

